home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
- *
- * (b) If this Sample Code is distributed as part of the Display PostScript
- * System Software Development Kit from Adobe Systems Incorporated,
- * then this copy is designated as Development Software and its use is
- * subject to the terms of the License Agreement attached to such Kit.
- *
- * (c) If this Sample Code is distributed independently, then the following
- * terms apply:
- *
- * (d) This file may be freely copied and redistributed as long as:
- * 1) Parts (a), (d), (e) and (f) continue to be included in the file,
- * 2) If the file has been modified in any way, a notice of such
- * modification is conspicuously indicated.
- *
- * (e) PostScript, Display PostScript, and Adobe are registered trademarks of
- * Adobe Systems Incorporated.
- *
- * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
- * CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
- * AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
- * ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
- * OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
- * WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
- * WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
- * DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
- * OF THIRD PARTY RIGHTS.
- */
-
- /*
- * DocView.m
- *
- * This class handles the scaling of the drawing view. It repositions
- * the drawing view within itself if the drawing view is smaller than the
- * size of the clip view. The size of the doc view is:
- * MAX(clip view frame, drawing view frame).
- *
- * Version: 2.0
- * Author: Ken Fromm
- * History:
- * 03-07-91 Added this comment.
- */
-
- #import "DetectApp.h"
- #import "DocView.h"
- #import "DrawingView.h"
- #import "DrawingViewWraps.h"
-
- #import <appkit/NXCursor.h>
- #import <appkit/NXImage.h>
- #import <appkit/Matrix.h>
- #import <appkit/ScrollView.h>
- #import <dpsclient/wraps.h>
- #import <appkit/nextstd.h>
-
- @implementation DocView
-
- /*
- * Since there is only one subview its easier to keep track of it as an
- * instance variable rather than in the subview list. Returns the
- * previous drawing view.
- */
- - addDrawView:subView
- {
- id oldView;
-
- oldView = drawviewId;
- [oldView removeFromSuperview];
-
- [self addSubview:subView];
- drawviewId = subView;
-
- return oldView;
- }
-
- /*
- * Change the menu title and toggle the trace boolean
- */
- - traceZoom:sender
- {
- if (!tracezoom)
- [[sender selectedCell] setTitle:"Zooming On"];
- else
- [[sender selectedCell] setTitle:"Zooming Off"];
-
- tracezoom = !tracezoom;
-
- return self;
- }
-
- /* Returns whether tracing should be turned on when zooming. */
- - (BOOL) isTraceZooming
- {
- return tracezoom;
- }
-
- /* Sets and returns the scale for the drawing view. */
- - setScale:(float)value
- {
- scale = value;
-
- return self;
- }
-
- - (float) scale
- {
- return scale;
- }
-
- /*
- * Returns the size of the control point scaled to reflect the
- * current scale. If the scaling were not done, a control point
- * would look like the USS Enterprise at 400%. (The aircraft
- * carrier.)
- *
- */
- - (float) controlPointSize
- {
- return FONTSIZE * (1.0/scale);
- }
-
- /*
- * Returns a scaled the hit setting. Using an unscaled hit setting would be
- * like using a boxing glove at 400% scale.
- */
- - (float) hitSetting
- {
- return [NXApp hitSetting] * (1.0/scale);
- }
-
-
- - (BOOL) isZooming
- {
- return zooming;
- }
-
- /*
- * Check whether the frame of the drawingview is in the rectangle passed in.
- * If drop is true, then include the linewidth and the drop shadow as part of the
- * drawingview frame.
- */
- - getDrawViewInRect:(const NXRect *) aRect withDrop:(BOOL) drop
- {
- id aView = NULL;
-
- NXRect viewRect, dropRect;
-
- [drawviewId getFrame:&viewRect];
- if (drop)
- {
- dropRect = viewRect;
- NXOffsetRect(&dropRect, rint(OFFSET * scale), rint(-OFFSET * scale));
- NXOffsetRect(&viewRect, rint(LINEWIDTH/2 * scale), rint(LINEWIDTH/2 * scale));
- NXUnionRect(&dropRect, &viewRect);
- }
- if (NXIntersectsRect(aRect, &viewRect))
- aView = drawviewId;
-
- return aView;
- }
-
- /*
- * This method is overridden from the View class. When the
- * user is zooming the cursor rect for the zoom cursor is set
- * the the frame of the drawing view.
- */
- - resetCursorRects
- {
- id imageId, visView;
-
- NXPoint hotspot;
-
- NXRect cursorRect, visRect;
-
- if (zooming)
- {
- if (!zoomCursor)
- {
- hotspot.x = hotspot.y = 8.0;
- imageId = [NXImage newFromSection:"zoom.tiff"];
- zoomCursor = [NXCursor newFromImage:imageId];
- [zoomCursor setHotSpot:&hotspot];
- }
-
- [self getVisibleRect:&visRect];
- visView = [self getDrawViewInRect:&visRect withDrop:NO];
- if (visView)
- {
- [visView getFrame:&cursorRect];
- NXIntersectionRect(&visRect, &cursorRect);
- [self addCursorRect:&cursorRect cursor:zoomCursor];
- }
- else
- zooming = NO;
- }
-
- return self;
- }
-
- /*
- * Messaged from the zoom matrix. Starts the zoom loop. At the next
- * mouse down in the drawing view, the scaleDrawView:toPoint: method
- * will be called.
- */
- - zoom:sender
- {
- zooming = YES;
- zoomControl = sender;
- [self resetCursorRects];
-
- [window makeKeyAndOrderFront:self];
-
- return self;
- }
-
- /*
- * Sizes the drawing view from the old scale to the new scale.
- * The frame of the view is used because it provides the size
- * of the view in default coordinates. The bounds of the view
- * provides the size in scaled coordinates. As a result, the
- * bounds will always be the same regardless of the scale.
- */
- - sizeView:viewId withScale:(float) newscale
- {
- float scalefactor, sizewidth, sizeheight;
-
- NXRect viewFrame;
-
- [viewId getFrame:&viewFrame];
- scalefactor = newscale/scale;
- sizewidth = viewFrame.size.width*scalefactor;
- sizeheight = viewFrame.size.height*scalefactor;
- [viewId sizeTo:rint(sizewidth) :rint(sizeheight)];
-
- return self;
- }
-
- /*
- * Scales the drawing view from the old scale to the new scale.
- * The scale method is relative so we use the ratio
- * of the old scale to the new scale to obtain the scaling factor.
- */
- - scaleView:viewId withScale:(float) newscale
- {
- float scalefactor;
-
- scalefactor = newscale/scale;
- [viewId scale:scalefactor :scalefactor];
-
- return self;
- }
-
- /*
- * Place the view passed in in the center of the doc view
- * if it is smaller than the size of the ClipView. Scroll bars
- * are added or deleted depending on whether or not they
- * are needed. (They can always appear but we've chosen
- * to show them conditionally in this example.
- *
- * Two passes are made through the loop because adding
- * or removing a horizontal or vertical scrollbar will
- * affect the size of the remaining dimension .
- */
- - placeView:viewId
- {
- BOOL vert = NO, horiz = NO, done = NO;
-
- int passes = 0, border_type;
-
- float margin;
-
- NXSize contSize, newSize, insetSize, delta;
-
- NXRect viewFrame, scrollFrame;
-
- margin = 4 * OFFSET * scale;
-
- [viewId getFrame:&viewFrame];
- [[superview superview] getFrame:&scrollFrame];
- border_type = [[superview superview] borderType];
-
- while (!done && ++passes <= 2)
- {
- [ScrollView getContentSize:&contSize forFrameSize:&scrollFrame.size
- horizScroller:horiz vertScroller:vert borderType:border_type];
-
- newSize.width = MAX(viewFrame.size.width, contSize.width);
- newSize.height = MAX(viewFrame.size.height, contSize.height);
-
- delta.width = newSize.width - viewFrame.size.width;
- delta.height = newSize.height - viewFrame.size.height;
- if (delta.width != 0.0 || delta.height != 0.0)
- {
- if (delta.width < margin)
- newSize.width += margin - delta.width;
- if (delta.height < margin)
- newSize.height += margin - delta.height;
- }
-
- horiz = (newSize.width != contSize.width);
- vert = (newSize.height != contSize.height);
- if ((horiz && vert) || (!horiz && !vert))
- done = YES;
- else
- done = NO;
- }
-
- [self sizeTo:newSize.width :newSize.height];
-
- insetSize.width = floor((newSize.width - viewFrame.size.width)/2);
- insetSize.height = floor((newSize.height - viewFrame.size.height)/2);
- [viewId moveTo:insetSize.width :insetSize.height];
- if (insetSize.width != 0 || insetSize.height != 0)
- [viewId setClipping:YES];
- else
- [viewId setClipping:NO];
-
- if (horiz)
- [[superview superview] setHorizScrollerRequired:YES];
- else
- [[superview superview] setHorizScrollerRequired:NO];
-
- if (vert)
- [[superview superview] setVertScrollerRequired:YES];
- else
- [[superview superview] setVertScrollerRequired:NO];
-
- return self;
- }
-
- /*
- * Scales the view to the tag of the selected matrix cell and then
- * scrolls to the point. The point is in window coordinates so
- * it must be converted to the drawing view coordinates in order
- * to position it in the same relative place in the view.
- */
- - scaleDrawView:hitView toPoint:(NXPoint *) p;
- {
- float newscale;
-
- NXPoint viewPt;
-
- [window invalidateCursorRectsForView:self];
- newscale = [zoomControl selectedTag] * 0.01;
- if (hitView && newscale != scale)
- {
- /* Convert the point to the hitView's coordinates. */
- viewPt = *p;
- [hitView convertPoint:&viewPt fromView:nil];
- [window disableDisplay];
- /*
- * Size and then scale the drawing view. The frame of the
- * drawing view must reflect the changed size. Scaling
- * alone will not change the frame.
- */
- [self sizeView:hitView withScale:newscale];
- [self scaleView:hitView withScale:newscale];
- [self setScale:newscale];
-
- [self placeView:hitView];
- [self scrollPoint:&viewPt inView:hitView to:p];
- [window reenableDisplay];
-
- /* Trace the zoom if the menu option is set. */
- if (tracezoom)
- DPSTraceContext(DPSGetCurrentContext(), YES);
-
- [[window contentView] display];
-
- if (tracezoom)
- DPSTraceContext(DPSGetCurrentContext(), NO);
- }
- zooming = NO;
-
- return self;
- }
-
-
- /*
- * Use the point location relative to the window versus the point relative
- * to the drawing view (before the scale) to determine where to scroll
- * the drawing view. We want the same location in the drawing view to
- * appear where the mouse downed occurred. The window coordinates
- * are used and then adjusted by the position of the scrolling frame
- * because the presence or absence of scrollbars throws the use
- * of the doc views coordinates awry.
- */
- - scrollPoint:(const NXPoint *) aPt inView:hitView to:(const NXPoint *) windowPt
- {
- NXPoint viewPt;
-
- NXSize contSize;
-
- NXRect viewFrame, visRect, scrollFrame;
-
- [[superview superview] getContentSize:&contSize];
- [hitView getFrame:&viewFrame];
-
- if (viewFrame.size.width > contSize.width || viewFrame.size.height > contSize.height)
- {
- viewPt = *aPt;
- [self convertPoint:&viewPt fromView:hitView];
- [self getVisibleRect:&visRect];
- [[superview superview] getFrame:&scrollFrame];
-
- if (viewFrame.size.width > contSize.width)
- viewPt.x -= windowPt->x - (scrollFrame.origin.x +scrollFrame.size.width -
- visRect.size.width);
-
- if (viewFrame.size.height > contSize.height)
- viewPt.y -= windowPt->y - (scrollFrame.origin.y + scrollFrame.size.height -
- visRect.size.height);
-
- [self scrollPoint:&viewPt];
- }
-
- return self;
- }
-
- /*
- * This drawSelf method draws a border around the drawing view as well as a
- * drop shadow. This is only done if it will be visible however. We tell if it is visible
- * if the rectangle passed in is not contained entirely within the drawingView.
- */
- - drawSelf:(NXRect *)r :(int) count
- {
- id visView;
-
- NXRect drawRect, dropRect;
-
- visView = [self getDrawViewInRect:r withDrop:YES];
- if (visView)
- {
- [visView getFrame:&drawRect];
- if (!NXContainsRect(&drawRect, r))
- {
- dropRect = drawRect;
- NXOffsetRect(&dropRect, rint(OFFSET * scale), rint(-OFFSET * scale));
-
- PSgsave();
- PSsetgray(NX_BLACK);
- PSsetlinewidth(LINEWIDTH * scale);
- PSrectclip(r->origin.x, r->origin.y, r->size.width, r->size.height);
- PSrectfill(dropRect.origin.x, dropRect.origin.y,
- dropRect.size.width, dropRect.size.height);
- PSrectstroke(drawRect.origin.x, drawRect.origin.y,
- drawRect.size.width, drawRect.size.height);
- PSgrestore();
- }
- }
-
- return self;
- }
-
- @end
-
-